home *** CD-ROM | disk | FTP | other *** search
Wrap
var EXPORTED_SYMBOLS = ["YOONO_SERVER"]; Components.utils.import("resource://yoono/yoonoPrefs.js"); var yoono = {}; var log = {info:function() {},debug:function() {},warn:function(){},error:function (){},fatal:function(){}}; // Globals const CI = Components.interfaces; const CL = Components.classes; const XMLHTTPREQUESTCOMPONENT = CL["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(); const PREFSSERVICE = CL["@mozilla.org/preferences-service;1"].getService(CI.nsIPrefService); const PREFS = PREFSSERVICE.getBranch("extensions.yoono."); const OBS = CL['@mozilla.org/observer-service;1'].getService(CI.nsIObserverService); // -> auto set commandQueueMgr Components.utils.import("resource://yoono/yoonoCommandQueue.js"); function Connection() { this.wrappedJSObject=this; this.xmlHttpRequest = XMLHTTPREQUESTCOMPONENT.QueryInterface(CI.nsIXMLHttpRequest); this.timer = CL['@mozilla.org/timer;1'].createInstance(CI.nsITimer); this.request = null; } Connection.prototype.init = function(y) { yoono = y; log = y.log; commandQueueMgr.init(y); commandQueueMgr.addObserver(this); } Connection.prototype.uninstall = function(y) { commandQueueMgr.uninstall(); } Connection.prototype.launch = function (command, arg) { if (('connect' != command) && YOONO_PREFS.get('nosynchro')) { log.debug("NoSync Pref is true: aborting command"); return ; } // creer le script et empiler les commandes non transient if (command) this.addToNextCommandScript(command, arg); } Connection.prototype.addToNextCommandScript = function(command, arg) { if (('connect' != command) && YOONO_PREFS.get('nosynchro')) { //log.debug("NoSync Pref is true: command ignored"); return ; } var request = this.createRequest(command, arg); if (!request.xml) return; if (request.transcient) commandQueueMgr.addTranscientRequest(request.xml); else commandQueueMgr.addTransactionalRequest(request.xml); } Connection.prototype.createRequest = function(command, arg) { var userCredential = yoono.main.getUserCredential(); if (!userCredential) { log.debug("Command ignored because no account"); return({xml:null}); } if(userCredential.anonymous && ('connect' != command)) { log.debug("Non-connect command ignored because anonymous"); return({xml:null}); } var transientCommand = false; var mkcmd = { xmlObj : new XML(), onNode : function() {} }; try { switch (command) { case 'connect' : if(userCredential.anonymous) arg = 'no-sync'; log.backtrace("connect with arg="+arg); switch(arg) { case "first-sync" : mkcmd.xmlObj = <connect client-sync-mode="first-sync"/>; break; case "manual-sync" : mkcmd.xmlObj = <connect client-sync-mode="manual-sync"/>; break; case "auto-sync" : mkcmd.xmlObj = <connect client-sync-mode="auto-sync"/>; break; case "no-sync" : mkcmd.xmlObj = <connect client-sync-mode="no-sync"/>; break; default : mkcmd.xmlObj = <connect/>; break; } transientCommand = true; break; case 'save-all-links' : log.debug("ADD SAVE ALL"); mkcmd.xmlObj = <save-all-links/>; mkcmd.onNode = function(node) { if (node.isFolder()) return; this.xmlObj.appendChild(node.setAllAttributes(<link />)); } yoono.bkm.getCurrentTree().traverseNode(mkcmd); break; case 'save-all-links-add' : log.debug('begin save-all-links-add'); var notOnServer = arg; mkcmd.xmlObj = <save-all-links sync-id={YOONO_PREFS.get('syncid')} mode="ADD"/>; for each (var nodeList in notOnServer) { for each (var node in nodeList) { mkcmd.xmlObj.appendChild(node.setAllAttributes(<link />)); } } log.debug('end save-all-links-add'); break; case 'set-sync-id' : mkcmd.xmlObj = <save-all-links sync-id={YOONO_PREFS.get('syncid')} mode="ADD"/>; transientCommand = true; break; case 'add-link': if (!arg.isFolder()) mkcmd.xmlObj = arg.setAllAttributes(<add-link/>); break; case 'add-private-folder': if (arg.isFolder()) mkcmd.xmlObj = arg.setAllAttributes(<add-link private="client"/>); break; case 'remove-private-folder': if (arg.isFolder() ) mkcmd.xmlObj = arg.setAllAttributes(<remove-link/>); break; case 'publish-folder': var node = arg[0]; var publishedId = arg[1]; mkcmd.xmlObj = <add-xlink ref={":" + publishedId} path={"/$pub/" +publishedId}/> ; var path = node.getPath().toServer; var tmp = <update-link/>; tmp.appendChild(<old-link path={path}/>); tmp.appendChild(<new-link path={path} id={publishedId}/>); mkcmd.xmlObj += tmp; break; case 'unpublish-folder': var node = arg[0]; var publishedId = arg[1]; mkcmd.xmlObj = <remove-xlink ref={":" + publishedId} path={"/$pub/" +publishedId}/> ; var tmp = <update-link/>; var path = node.getPath().toServer; tmp.appendChild(<old-link path={path} id={publishedId}/>); tmp.appendChild(<new-link path={path}/>); mkcmd.xmlObj += tmp; break; case 'remove-link': mkcmd.xmlObj = arg.setAllAttributes(<remove-link/>); break; case 'update-link': var oldNode = arg[0]; var newNode = arg[1]; if (oldNode.isAcceptable() && !newNode.isAcceptable()) { this.addToNextCommandScript('remove-link', oldNode); return; } if (!oldNode.isAcceptable() && newNode.isAcceptable()) { this.addToNextCommandScript('add-link', newNode); return; } if (!oldNode.isAcceptable() && !newNode.isAcceptable()) { return; } if (!oldNode.isFolder()) { mkcmd.xmlObj = <update-link/>; mkcmd.xmlObj.appendChild(oldNode.setAllAttributes(<old-link/>)); mkcmd.xmlObj.appendChild(newNode.setAllAttributes(<new-link/>)); } break; case 'load-all-links' : // The load-all-links command is always processed last, whatever its position in the request mkcmd.xmlObj = <load-all-links/>; break; case 'compute-recommended-links': var newbkmarg = 'url:' + arg.url + ',title:' + arg.title; mkcmd.xmlObj = <compute-recommended-links url={arg.url} client-newbkm={newbkmarg} size={1} />; transientCommand = true; break; default: log.error ('no such command in yoonoService.createRequest : ' + command); break; } } catch(e) { log.exception(e); } return { xml : mkcmd.xmlObj, transcient : transientCommand, overrideSyncId : false }; } // handle the response to the request containing the commands stored in runningScript and runningFile // according to response, it might be necessary to run again the commands after they were updated // // (be warn, $this isn't $this! because this function is called witout his environnement) Connection.prototype.onSendingRequest = function(req) { yoono.dialogs.setThrobberBusy(true); } Connection.prototype.onRequestError = function(req) { OBS.notifyObservers (this, "yoono-get-response", "error"); yoono.dialogs.setThrobberFailed(); } var safePreferences = { bookmarksLastModified: true, synchroaction: true, synchroask : true, syncid : true, userid : true } Connection.prototype.onRequestSuccess = function(req, result) { // Notify each request (primary for unit testing) try { OBS.notifyObservers (this, "yoono-get-response", result); } catch(e) {log.exception(e)} // Handle commands to update preferences yoono.main.getServerContextData(result); var newCommand = false; var replace = false; yoono.dialogs.setThrobberBusy(false); // creation d'un nouvel utilisateur if (!YOONO_PREFS.get('userid')) YOONO_PREFS.set('userid', result.context['user-id'].toString(), PREFS.PREF_STRING); // If invalid Id, do nothing (handled by sidebar that) if (result['display-error'].@code == 'ERROR_INVALID_USER_ID') { return; } var requestSync = result['request-sync'].@code; if (result['display-error'].@code == 'ERROR_INTERNAL_ERROR') return log.error("Internal error"); // Sync id was different on server if (requestSync == 'REQUEST_SYNC_INVALID_SYNC_ID') { yoono.main.addStat(['invalid_sync_id']); log.debug("request-sync sync-mode="+result['request-sync'].@['client-sync-mode']); var serverLinks = result['request-sync'].@['link-count']; var clientLinks = yoono.bkm.getNbBkms(); log.debug("Nb of bkms on server : " + serverLinks); log.debug("Nb of bkms on client : " + clientLinks); // ask user if( result['request-sync'].@['client-sync-mode'] == "manual-sync" ) { // When user enables sync and no link on server, export ! YOONO_PREFS.set('synchroaction', 'merge', PREFS.PREF_STRING); if(0 == serverLinks) { YOONO_PREFS.set('synchroaction', 'export', PREFS.PREF_STRING); } else { if (YOONO_PREFS.get('synchroask')) // don't ask for unittest (there is no way to set this pref to false, except manually!) yoono.dialogs.setDialog('synchroask'); } } else if( result['request-sync'].@['client-sync-mode'] == "first-sync" ) { YOONO_PREFS.set('synchroaction', 'export', PREFS.PREF_STRING); } else if( result['request-sync'].@['client-sync-mode'] == "no-sync" ) { return; } else { YOONO_PREFS.set('synchroaction', 'import', PREFS.PREF_STRING); // If no link on server, sync has been disabled on another client : disable this client sync if(0 == serverLinks) { YOONO_PREFS.set('nosynchro', true, PREFS.PREF_BOOL); } else { // Test difference between number of bkms on server and on client. // if difference > some threshold, ask user. var threshold = YOONO_PREFS.get('bkm.ask.threshold') || 10; if(Math.abs(serverLinks - clientLinks) > threshold && YOONO_PREFS.get('synchroask')) { // don't ask for unittest (there is no way to set this pref to false, except manually!) YOONO_PREFS.set('synchroaction', 'merge', PREFS.PREF_STRING); log.debug("Difference > threshold, asking what to do"); yoono.dialogs.setDialog('synchroask'); } } } log.debug("REQUEST_SYNC_INVALID_SYNC_ID: must perform '" + YOONO_PREFS.get('synchroaction') + "'"); if (YOONO_PREFS.get('synchroaction') == 'merge' || YOONO_PREFS.get('synchroaction') == 'import') { // Re run the same commands, with the server syncid newCommand = yoono.server.createRequest('load-all-links'); newCommand.overrideSyncId = result['request-sync'].@['server-sync-id']; } else if (YOONO_PREFS.get('synchroaction') == 'export') { // Overwrite running command with an save-all-links command newCommand = yoono.server.createRequest('save-all-links'); yoono.dialogs.synchroinfos('export', yoono.bkm.bookmarksNumber() ); } else if (YOONO_PREFS.get('nosynchro')) { // In case of user registration, wizard might be waiting for the end of the sync : OBS.notifyObservers (this,"yoono-synchro-end",YOONO_PREFS.get('synchroaction')); YOONO_PREFS.resetSynchro(); return; } else { // rajoute une securite au cas ou la valeur a ete modifiee YOONO_PREFS.resetSynchro(); newCommand = yoono.server.createRequest('load-all-links'); } } else if (requestSync == 'REQUEST_SYNC_NEW_USER') { // Overwrite running command with an save-all-links command newCommand = yoono.server.createRequest('save-all-links'); } else { log.debug('Nothing to do : notify so that sidebar wizard knows it can proceed, but knows sync was not necessary'); OBS.notifyObservers (this,"yoono-synchro-useless",YOONO_PREFS.get('synchroaction')); } // The load-all-links command is always processed last, whatever its position in the request var importlinks = result['import-links']; if (importlinks.@code == 'MSG_LINKS_LOADED') { // If some persistent commands are in the 'next' commands buffers, it means new modifications have been made by the user // The imported links must not be used then, in order not to undo these new modifications. // The load-all-links command is added to the 'next' commands buffers to be performed at the end of the request // that sends the new modifications if(commandQueueMgr.nextPersistentCommandIsEmpty()) { log.debug('Next command is empty, processing loadAllLinks'); var resp = yoono.bkm.loadAllLinks(importlinks.elements('link')); if (resp.action == 'import') { yoono.dialogs.synchroinfos("import", resp.imported); } else if (resp.action == 'merge') { yoono.dialogs.synchroinfos("merge", resp.added); } // was loadAllLinks successful ? if( resp.clearCommands == true ) { // perform a set-sync-id newCommand = yoono.server.createRequest('set-sync-id'); } } else { log.debug('Next command not empty, discarding loaded links and queueing load-all-links again'); yoono.server.addToNextCommandScript('load-all-links'); } } //log.debug(" new Command : "+(newCommand?newCommand.xml.toXMLString():"no")+" from "+req.map(function (r){return r.toXMLString();}).join(' \n')+" => "+result.toXMLString()); return newCommand; } var YOONO_SERVER = new Connection();